// PropertyFactory.cpp: implementation of the PropertyFactory class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PropertyFactory.h"
#include "OriginalPropertySet.h"
#include "DBVariable.h"
#include "NonDBVariable.h"
#include "CustomDBVariable.h"
#include "CustomNonDBVariable.h"
#include "ProductCatalogManager.h"
#include "PersistentFacade.h"
#include "Standard.h"
#include "KnownPartSet.h"
#include "PartTypeVariable.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

using namespace JointSystem;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
namespace PropertySystem
{
	const CString PropertyFactory::PARTIDPRONAME = _T("CUSTOMID");
	const CString PropertyFactory::DESCRIPTION = _T("DESC");
	const CString PropertyFactory::STANDARD = _T("STAND");
	const CString PropertyFactory::SPEC = _T("SPEC");
	
	PropertyFactory& PropertyFactory::Instance()
	{
		static PropertyFactory theFactory;
		return theFactory;
	}

	PropertyFactory::PropertyFactory()
	{
		
	}
	
	PropertyFactory::~PropertyFactory()
	{
		RemoveAll();
	}

	PropertyStack& PropertyFactory::GetProperty(const CString& strPartID, const CString& strStandard)
	{
		ASSERT(!strPartID.IsEmpty());
		ASSERT(!strStandard.IsEmpty());

		PropertyStack* pStack = NULL;
		CString strKey = strPartID + strStandard;
		pStack = FindPropertyStack(strKey);
		if(pStack != NULL)
			return *pStack;

		pStack = NewPropertyStack(strPartID, strStandard);
		ASSERT(pStack);

		AddPropertyStack(strKey, pStack);

		return *pStack;
	}
	
	PropertyStack* PropertyFactory::FindPropertyStack(const CString& strKey)
	{
		PropertyStack* pStack = NULL;

		m_thePropertyTemplate.Lookup(strKey, pStack);

		return pStack;
	}

	void PropertyFactory::AddPropertyStack(const CString& strKey, PropertyStack* pStack)
	{
		ASSERT(pStack);

		m_thePropertyTemplate.SetAt(strKey, pStack);
	}

	BOOL PropertyFactory::GetOPropertySet(OriginalPropertySet& OPropertySet, const CString& strPartID, const CString& strStandard)
	{
		ASSERT(!strStandard.IsEmpty());
		ASSERT(!strPartID.IsEmpty());

		CString strPropertyTable;
		CString strSource;

		ProductCatalog* pCatalog = ProductCatalogManager::Instance()->GetProductCatalog(strStandard);
		ASSERT(pCatalog);
		Standard* pStandard = GetPersistentFacade().GetStandardGenerator()->Generate(pCatalog);
		ASSERT(pStandard);

		strPropertyTable = pStandard->PropertyTable();
		strSource = pCatalog->DataSourceURI();

		return OPropertySet.GetOriginalPropertySet(strPartID, strPropertyTable, strSource);
	}

	PropertyStack* PropertyFactory::NewPropertyStack(const CString& strPartID, const CString& strStandard)
	{

		ASSERT(!strPartID.IsEmpty());
		ASSERT(!strStandard.IsEmpty());

		OriginalPropertySet OPropertySet;
		BOOL bResult = GetOPropertySet(OPropertySet, strPartID, strStandard);
		ASSERT(bResult);

		OriginalProperty* pOProperty = NULL;
		PropertyStack* pStack = new PropertyStack;
		ASSERT(pStack);


		pOProperty = OPropertySet.GetFirst();
		while(pOProperty != NULL)
		{
			PropertyVariable* pVariable = GenerateVariable(pOProperty);
			ASSERT(pVariable);

			pStack->AddProperty(pVariable);

			pOProperty = OPropertySet.GetNext();
		}

		PartSortPropertySet* pSet = KnownPartSet::Instance().GetPartSortPropertySet(strStandard);
		ASSERT(pSet);

		PartSortProperty* pSPro = pSet->GetPartSortProperty(strPartID);

		if(pSPro != NULL && !pSPro->Parent().IsEmpty())
		{
			PropertyStack& stack = GetProperty(pSPro->Parent(), strStandard);
			
			PropertyVariable* pVar = NULL;
			PropertyStack::Iterator *it = stack.NewIterator();
			for(it->Begin(); !it->End(); it->Next())
			{
				pVar = static_cast<PropertyVariable*>(it->Get());
				ASSERT(pVar);
				PropertyVariable* pTempVar = pVar->Clone();
				ASSERT(pTempVar);
				pStack->AddProperty(pTempVar);
			}
			delete it;
		}
		this->GeneratorInhenceProperty(pStack, this->PARTIDPRONAME, strPartID);
		this->GeneratorInhenceProperty(pStack, this->STANDARD, strStandard);
		if(pSPro != NULL)
		{
			this->GeneratorInhenceProperty(pStack, this->DESCRIPTION, pSPro->Description());
//			this->GeneratorInhenceProperty(pStack, this->SPEC, pSPro->SpecFormat());
		}
		
		return pStack;
	}

	PropertyVariable* PropertyFactory::GenerateVariable(const OriginalProperty* pOProperty)
	{
		ASSERT(pOProperty);

		return pOProperty->GenerateVariable();
	}

	void PropertyFactory::RemoveAll()
	{
		PropertyStack* pStack = NULL;
		CString strKey;

		POSITION pos = m_thePropertyTemplate.GetStartPosition();

		while(pos != NULL)
		{
			m_thePropertyTemplate.GetNextAssoc(pos, strKey, pStack);
			pStack->RemoveAll();
			delete pStack;
		}
		m_thePropertyTemplate.RemoveAll();
	}

	void PropertyFactory::UpdatePropertyStack()
	{
		RemoveAll();
	}

	void PropertyFactory::GeneratorInhenceProperty(PropertyStack* pStack, const CString& strName, const CString& strValue)
	{
		ASSERT(!strValue.IsEmpty());

		PropertyVariable* pPV = pStack->GetProperty(strName);
		if(pPV == NULL)
		{
			NonDBVariable* pVariable = new NonDBVariable;
			ASSERT(pVariable);
			pVariable->PropertyStyle(PropertyVariable::eNONDB);
			pVariable->DataType(Variable::STRING);
			pVariable->Symbol(strName);
			pPV = pVariable;
			pStack->AddProperty(pVariable);
		}
		*static_cast<Variable*>(pPV) = strValue;
	}
};
